#include <iostream>
#include <vector>
#include <string>
#define M 13

int scope_level;

using namespace std;

class symbol
{
friend class hash_table;
	
public:
	string status;
	symbol(string n,string t,string v);
	~symbol();
	string name;
	string type;
	string value;
	void print();

	private:

};
symbol::symbol(string n,string t,string v)
{
	name=n;
	type=t;
	value=v;
	status="NIL";
}

symbol::~symbol()
{
	name="NIL";
	type="NIL";
	value="NIL";
	status="NIL";
}
void symbol::print()
{
	cout<<name<<endl<<type<<endl<<value<<endl<<status<<endl;
}

class hash_table
{
public:
hash_table();
int hash_function(string key,int i);
symbol* hash[M+1];
int hash_insert(string n,string t,string v);
int hash_search(string n);
int hash_search_insert(string n,string t,string v);
};

hash_table::hash_table()
{
for (int i=0;i<M+1;i++)
{
	hash[i]=new symbol("NIL","NIL","NIL");
}
}

//hash_table::~hash_table()
//{
//	for (int i=0;i<M+2;i++)
//		hash[i]=0;
//}

int hash_table::hash_function(string key, int i)
{
int key_length;
int init_value;
int map_value;

key_length=key.length();
init_value=key[0]-65;

map_value=(init_value+key_length+i)%M;
return map_value;
}

int hash_table::hash_insert(string n,string t,string v)
{
int i;
string key;
int map_value;

i=0;
key=n;

while(i!=M)	{
	map_value=hash_function(key,i);
	cout<<"hash insert map value: "<<map_value<<" for name: "<<key<<endl;
	cout<<"hash map value status: "<<hash[map_value]->status<<endl;
	cout<<i<<endl;
	if (hash[map_value]->status=="NIL"||hash[map_value]->status=="DEL")
	{	
		hash[map_value]->name=n;
		hash[map_value]->type=t;
		hash[map_value]->value=v;
		hash[map_value]->status="FIL";
		return map_value;
	}
	i++;
}
	if (i==M)
	{
		cout<<"hash table overflower"<<endl;
		return -1;
	}
}

int hash_table::hash_search(string n)
{
	int i;
	int map_value;
	string key;

	key=n;
	i=0;

	while(i!=M) {
		map_value=hash_function(key,i);
//		cout<<"maped value in the hash table: "<<hash[map_value]->name<<endl<<"value search for: "<<key<<"status of value in hash table: "<<hash[map_value]->status<<endl;
		if ((hash[map_value]->name==key)&&(hash[map_value]->status=="FIL"))
		{
//			cout<<"key: "<<key<<" found in hash table: "<<"hash["<<map_value<<"] "<<hash[map_value]->name<<endl;
//			cout<<hash[map_value]->status<<endl;
			return map_value;
		}
		i++;
	}
	if (i==M)
	{
		cout<<"Symbol not found :"<<n<<endl;
	}
	return -1;
}

int hash_table::hash_search_insert(string n,string t,string v)
{
	int result;
	
	result=hash_search(n);
	if (result==-1)
	{
		result=hash_insert(n,t,v);
		return result;
	}
	else
		cout<<n<<" already exits in current scope"<<endl;
	return -1;
}

class scope_stack()
hash_table* enter_new_scope()
{
	scope_level++;
	T[scope_level]=new hash_table();
	return T[scope_level];
}

void leave_current_scope()
{
	scope_level--;
	return;
}

int main()
{	

	int result;
	hash_table T;
	result=T.hash_search("a");
	cout<<"result for search a: "<<result<<endl;
	result=T.hash_insert("a","int","0");
	cout<<"result for insert a first time: "<<result<<endl;
	if (result!=-1)
	{
		cout<<"symbol in hash table: "<<endl;
		T.hash[result]->print();
	}
	result=T.hash_insert("b","int","0");
	cout<<"result for insert b : "<<result<<endl;
	result=T.hash_search("a");
	cout<<"result for search 'a' second time "<<result<<endl;
	result=T.hash_insert("a","int","0");
	cout<<"result for insert 'a' second time "<<result<<endl;
	T.hash[result]->print();
	enter_new_scope();
	cout<<scope_level;
	leave_current_scope();
	cout<<scope_level;
}
